import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

import '../../config/ApiConfig.dart';
import 'ResponseData.dart';

class Log{
  static JsonEncoder encoder = const JsonEncoder.withIndent('  ');

  static _getDeviceInfo() async {
    MethodChannel channel = const MethodChannel("channel_device");
    var result = await channel.invokeMethod("device_info");
    return result;
  }

  /// 接口请求错误
  static writeResponseLog(Response response) {
    if(kDebugMode){
      return;
    }
    if(!Platform.isAndroid){
      return;
    }

    Future(()async{
      try {
        var now = DateTime.now();
        var time = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);

        Map<String,dynamic>? log = {"time":time};
        log["deviceInfo"] = await _getDeviceInfo();
        log["userId"] = ApiConfig.userId;
        log["userName"] = ApiConfig.userName;
        log["userCode"] = ApiConfig.userCode;

        var options = response.requestOptions;
        log["url"] = "${options.baseUrl}${options.path}";
        log["headers"] = options.headers;

        if(options.queryParameters.isNotEmpty){
          log["parametersGET"] = options.queryParameters;
        }
        if(options.data != null){
          log["parametersPost"] = options.data;
        }

        log["code"] = response.statusCode ?? 0;
        log["message"] = response.statusMessage ?? "";
        if(response.data is ResponseData){
          log["responseData"] = (response.data as ResponseData).toJson();
        }else{
          log["responseData"] = "${response.data}";
        }

        var content = encoder.convert(log);

        final dir = await getExternalStorageDirectory();
        File file = File('${dir!.path}/log.txt');
        if (!file.existsSync()) {
          file.createSync();
        }

        var length = file.lengthSync();
        FileMode mode = FileMode.append;
        if(length > 50 * 1024 * 1024){
          mode = FileMode.write;
        }
        file.writeAsStringSync("$content\n\n\n\n\n",mode: mode);

        log.clear();
        log = null;
      } catch (e) {
      }
    });
  }

  /// 接口请求错误
  static writeErrorNetLog(DioError err){
    if(kDebugMode){
      return;
    }
    if(!Platform.isAndroid){
      return;
    }
    Future(()async{
      try {
        var now = DateTime.now();
        var time = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);

        Map<String,dynamic>? log = {"time":time};
        log["deviceInfo"] = await _getDeviceInfo();
        log["userId"] = ApiConfig.userId;
        log["userName"] = ApiConfig.userName;
        log["userCode"] = ApiConfig.userCode;

        var options = err.requestOptions;
        log["url"] = "${options.baseUrl}${options.path}";
        log["headers"] = options.headers;

        if(options.queryParameters.isNotEmpty){
          log["parametersGET"] = options.queryParameters;
        }
        if(options.data != null){
          log["parametersPost"] = options.data;
        }

        log["code"] = err.response?.statusCode ?? 0;
        log["message"] = err.response?.statusMessage ?? "";
        log["error"] = "${err.error}";
        log["responseData"] = err.response?.data ?? {};

        var content = encoder.convert(log);

        final dir = await getExternalStorageDirectory();
        File file = File('${dir!.path}/log.txt');
        if (!file.existsSync()) {
          file.createSync();
        }

        var length = file.lengthSync();
        FileMode mode = FileMode.append;
        if(length > 50 * 1024 * 1024){
          mode = FileMode.write;
        }
        file.writeAsStringSync("$content\n\n\n\n\n",mode: mode);

        log.clear();
        log = null;
      } catch (e) {
      }
    });
  }

  /// 错误日志
  static writeErrorTraceLog(FlutterErrorDetails details){
    if(kDebugMode){
      return;
    }
    if(!Platform.isAndroid){
      return;
    }
    Future(()async{
      try {
        var time = DateFormat("yyyy-MM-dd HH:mm:ss").format(DateTime.now());

        Map<String,dynamic>? log = {"time":time};
        log["deviceInfo"] = await _getDeviceInfo();
        log["userId"] = ApiConfig.userId;
        log["userName"] = ApiConfig.userName;
        log["userCode"] = ApiConfig.userCode;

        log["exception"] = "${details.exception}";
        log["stack"] = _getStackTraceString(details.stack);

        var content = encoder.convert(log);

        final dir = await getExternalStorageDirectory();
        File file = File('${dir!.path}/log.txt');
        if (!file.existsSync()) {
          file.createSync();
        }

        var length = file.lengthSync();
        FileMode mode = FileMode.append;
        if(length > 50 * 1024 * 1024){
          mode = FileMode.write;
        }
        file.writeAsStringSync("$content\n\n\n\n\n",mode: mode);

        log.clear();
        log = null;
      } catch (e) {
      }
    });
  }

  /// 解析log日志，只取前面几行
  static _getStackTraceString(StackTrace? trace){
    if(trace == null){
      return {};
    }
    var traces = trace.toString().split("\n");
    if(traces.isEmpty){
      return {};
    }

    if(traces.length > 5){
      var map = {};
      for(int i = 0;i<=5;i++){
        map[i.toString()] = traces[i];
      }
      return map;
    }

    return {};
  }

  static writeLog(var text){
    if(kDebugMode){
      return;
    }
    if(!Platform.isAndroid){
      return;
    }
    Future(()async{
      try {
        var now = DateTime.now();
        var time = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);

        Map<String,dynamic>? log = {"time":time};
        log["deviceInfo"] = await _getDeviceInfo();
        log["userId"] = ApiConfig.userId;
        log["userName"] = ApiConfig.userName;
        log["userCode"] = ApiConfig.userCode;

        log["log"] = text;

        var content = encoder.convert(log);

        final dir = await getExternalStorageDirectory();
        File file = File('${dir!.path}/log.txt');
        if (!file.existsSync()) {
          file.createSync();
        }

        var length = file.lengthSync();
        FileMode mode = FileMode.append;
        if(length > 50 * 1024 * 1024){
          mode = FileMode.write;
        }
        file.writeAsStringSync("$content\n\n\n\n\n",mode: mode);

        log.clear();
        log = null;
      } catch (e) {
        print(e);
      }
    });
  }

}